public class SimpleHtmlParser {

	private String s;
	private int currentPosition = 0;
	private int lastAdvance = 0;

	public SimpleHtmlParser(String s) {
		this.s = s;
	}

	public boolean hasString(String sub) {
		int pos = s.substring(currentPosition).indexOf(sub);
		return (pos != -1);
	}

	public String extractUntilSubstring(String sub) {
		int subPos = s.substring(currentPosition).indexOf(sub);
		if (subPos > 0) {
			return extractNChars(subPos, sub.length());
		}
		return extractNChars(s.length() - 1 - currentPosition);
	}

	public String extractNChars(int n) {
		return extractNChars(n, 0);
	}

	public String extractNChars(int n, int suffix) {
		lastAdvance = n + suffix;
		currentPosition = currentPosition + lastAdvance;
		return s.substring(currentPosition - lastAdvance, currentPosition
				- suffix).trim();
	}

	public String extractUntilTag() {
		return extractUntilSubstringOrTag(null);
	}

	public String extractUntilSubstringOrTag(String sub) {
		int subPos = s.length() - 1 - currentPosition;
		if (sub != null) {
			subPos = s.substring(currentPosition).indexOf(sub);
		}
		int tagStartPos = s.substring(currentPosition).indexOf("<");
		if (subPos < tagStartPos) {
			return extractNChars(subPos, sub.length());
		}
		int tagEndPos = s.substring(currentPosition + tagStartPos).indexOf(">");
		return extractNChars(tagStartPos, tagEndPos + 1);
	}

	public int getCurrentPosition() {
		return this.currentPosition;
	}

	public void advance(int n) {
		this.currentPosition += n;
	}

	public void advance(String sub) {
		this.currentPosition += sub.length();
	}

	public void skipTag() {
		int tagStartPos = s.substring(currentPosition).indexOf("<");
		int tagEndPos = s.substring(currentPosition + tagStartPos).indexOf(">");
		advance(tagStartPos + tagEndPos + 1);
	}
	
	public boolean skipToNamedTag(String tagName) {
		int tagStartPos = s.substring(currentPosition).indexOf("<" + tagName);
		if (tagStartPos == -1) {
			return false;
		}
		int tagEndPos = s.substring(currentPosition + tagStartPos).indexOf(">");
		advance(tagStartPos + tagEndPos + 1);
		return true;
	}

	public void undoLast() {
		this.currentPosition = this.currentPosition - lastAdvance;
	}
	
	/**
	 * 
	 * @param skip
	 * @return false if string not found
	 */
	public boolean skipToEndOfString(String skip) {
		int pos = s.substring(currentPosition).indexOf("skip");
		if (pos != -1) {
			this.currentPosition += (pos + skip.length());
			return true;
		} 
		return false;
	}

	public String extractHref() {
		int hrefPos = s.substring(currentPosition).indexOf("href");
		if (hrefPos == -1) {
			return null;
		}

		int quoteBeginPos = hrefPos + 6;
		int quoteEndPos = s.substring(currentPosition + quoteBeginPos).indexOf("\"");
		int nextTagPos = s.substring(currentPosition + quoteBeginPos).indexOf("<");
		boolean abnormalQuoteTermination = false;
		String link = null;
		if (quoteEndPos != -1 && quoteEndPos < nextTagPos) {
			link = s.substring(currentPosition + quoteBeginPos, currentPosition + quoteBeginPos + quoteEndPos);
		} else {
			
			// Workaround for bad tag like this:
			// href="/homeinspectors/Florida/New Port R                <a href="/homeinspectors/Florida/Odessa.aspx"
			abnormalQuoteTermination = true;
			link = s.substring(currentPosition + quoteBeginPos, currentPosition + quoteBeginPos + nextTagPos);	
		}
		
		this.advance(quoteBeginPos + nextTagPos);

		return link;
	}

}
